//
// Created by LiuYou on 2021/11/25.
//

#ifndef HTTP_SERVER_COND_HPP
#define HTTP_SERVER_COND_HPP


#include <pthread.h>
#include <cstdio>
#include <cstring>
#include <stdexcept>
#include "MutexLock.hpp"


/**
 * @brief 和 Mutex类一样, 同为线程同步包装类。
 *
 * @note 没有考虑异常。
 * @see Mutex类, Sem类。
 *
 * @since 0.1
 * @author ly
 *
 * @version 0.1.1
 */
class Cond final {
public:
    explicit Cond(MutexLock& mutex) : mutexLock( mutex ) {
        int errNum = pthread_cond_init( &cond, nullptr );
        if (errNum != 0) {
            fprintf( stderr, "pthread_cond_init(): %s.\n", strerror( errNum ));
            throw std::runtime_error( std::string( "pthread_cond_init(): " ) + strerror( errNum ) + "." );
        }
    }

    ~Cond() {
        pthread_cond_destroy( &cond );
    }

    Cond(const Cond& rhs) = delete;

    Cond& operator=(const Cond& rhs) = delete;

    bool wait() {
        int errNum = pthread_cond_wait( &cond, &mutexLock.getMutex());
        if (errNum != 0) {
            fprintf( stderr, "pthread_cond_wait(): %s.\n", strerror( errNum ));
//            throw std::runtime_error( std::string( "pthread_cond_wait(): " ) + strerror( errNum ) + "." );
            return false;
        }
        return true;
    }

    bool notify() {
        int errNum = pthread_cond_signal( &cond );
        if (errNum != 0) {
//            throw std::runtime_error( std::string( "pthread_cond_signal(): " ) + strerror( errNum ) + "." );
            return false;
        }
        return true;
    }

    bool notifyAll() {
        int errNum = pthread_cond_broadcast( &cond );
        if (errNum != 0) {
//            throw std::runtime_error( std::string( "pthread_cond_broadcast(): " ) + strerror( errNum ) + "." );
            return false;
        }
        return true;
    }


private:
    /**
     * @brief 这里必须使用引用类型, 因为 Mutex是不支持拷贝的。
     */
    MutexLock& mutexLock;
    pthread_cond_t cond{};

};


#endif //HTTP_SERVER_COND_HPP
